/*
  * I2C用户态驱动示例代码
  * https://www.kernel.org/doc/html/v5.4/i2c/dev-interface.html
  */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>

/* Measure Relative Humidity, Hold Master Mode */
#define SI7020CMD_RH_HOLD	0xE5
/* Measure Temperature, Hold Master Mode */
#define SI7020CMD_TEMP_HOLD	0xE3
/* Software Reset */
#define SI7020CMD_RESET		0xFE

//调用i2c主设备文件接口和从设备通信（SI7006）
int main()
{
	//打开I2C主设备文件
	int fd = open("/dev/i2c-0", O_RDWR);
	if (fd < 0)
	{
		perror("/dev/i2c-0");
		return EXIT_FAILURE;
	}

	//设置从设备地址
	if (ioctl(fd, I2C_SLAVE, 0x40) < 0)
	{
		perror("ioctl");
		close(fd);
		return EXIT_FAILURE;
	}

	//复位传感器
	if (i2c_smbus_write_byte(fd, SI7020CMD_RESET))
	{
		perror("i2c_smbus_write_byte");
	}
	//等待传感器复位完成
	usleep(15000);
	//读温度
	int temp_code = i2c_smbus_read_word_data(fd, SI7020CMD_TEMP_HOLD);
	if (temp_code < 0)
	{
		perror("i2c_smbus_read_word_data");
	}
	//根据数据手册中的公式计算温度
	float temp = ntohs(temp_code) * 175.72 / 65536 - 46.85;
	printf("Temperature: %.1f\n", temp);

	//读湿度
	int rh_code = i2c_smbus_read_word_data(fd, SI7020CMD_RH_HOLD);
	if (rh_code < 0)
	{
		perror("i2c_smbus_read_word_data");
	}
	//根据数据手册中的公式计算湿度
	float humi = ntohs(rh_code) * 125.0 / 65536 - 6;
	printf("Humidity: %.1f\n", humi);

	close(fd);
	return 0;
}
